package com.tx.websocket.demo.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import com.tx.websocket.demo.common.BusinessException;
import com.tx.websocket.demo.common.OffsetBean;
import com.tx.websocket.demo.dao.ResourceDao;
import com.tx.websocket.demo.dao.RoleDao;
import com.tx.websocket.demo.dto.RoleResourceDto;
import com.tx.websocket.demo.model.BaseResource;
import com.tx.websocket.demo.model.Role;
import com.tx.websocket.demo.model.RoleResourceRel;
import com.tx.websocket.demo.service.RoleService;
import com.tx.websocket.demo.utils.CommonUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


@Service
public class RoleServiceImpl implements RoleService {

    @Resource
    private RoleDao roleDao;

    @Resource
    private ResourceDao resourceDao;

    @Transactional
    @Override
    public Integer addRole(Role role) {
        role.setCreateTime(new Date());
        role.setCreateUserId(CommonUtils.getUserId());
        return roleDao.addRole(role);
    }

    @Transactional(readOnly = true)
    @Override
    public List<Role> listRole(Role role, OffsetBean offsetBean) {
        return roleDao.listRole(role, offsetBean);
    }

    @Transactional(readOnly = true)
    @Override
    public Role getRoleByPrimaryKey(Long id) {
        return roleDao.getRoleByPrimaryKey(id);
    }

    @Transactional
    @Override
    public Integer delRoleByPrimaryKey(Long id) {
        return roleDao.delRoleByPrimaryKey(id);
    }

    @Transactional
    @Override
    public Integer updateRole(Role role) {
        role.setUpdateTime(new Date());
        return roleDao.updateRole(role);
    }

    @Override
    public List<Role> listRoleByUserId(Long userId) {
        return null;
    }

    @Override
    public Integer totalRole(Role role) {
        return roleDao.totalRole(role);
    }

    @Transactional
    @Override
    public void doRoleResourceBinding(Long roleId, List<Long> resourceIds) {
        roleDao.delRoleResRel(roleId);

        if(CollectionUtils.isEmpty(resourceIds))
            return;

        List<RoleResourceRel> roleResourceRels = new ArrayList<>();

        for(Long resourceId : resourceIds) {
            RoleResourceRel rel = new RoleResourceRel();
            rel.setResourceId(resourceId);
            rel.setRoleId(roleId);
            roleResourceRels.add(rel);
        }

        roleDao.insertRoleRes(roleResourceRels);
    }

    @Transactional(readOnly = true)
    @Override
    public RoleResourceDto doRoleResourceRel(Long roleId) {
        Role role = roleDao.getRoleByPrimaryKey(roleId);

        if(role == null)
            throw new BusinessException("不存在此角色");

        List<BaseResource> resources = getLayeredResources(roleId);
        return new RoleResourceDto(role, resources);
    }

    private List<BaseResource> getLayeredResources(Long roleId) {
        List<BaseResource> resources = resourceDao.listResources(null, null);
        List<BaseResource> haveReses = resourceDao.listResByRoleId(roleId);
        List<BaseResource> moduls = new ArrayList<>();
        List<BaseResource> categorys = new ArrayList<>();
        List<BaseResource> buttons = new ArrayList<>();

        for(BaseResource resource : resources) {
            if(resource.getType() == 0) moduls.add(resource);
            else if(resource.getType() == 1) categorys.add(resource);
            else buttons.add(resource);
            if(haveReses.contains(resource)) resource.setBeHave(true);
        }

        for(BaseResource res : categorys) {
            for(BaseResource r : buttons) {
                if(r.getParentId().equals(res.getId()))
                    res.getSubResources().add(r);
            }
        }

        for(BaseResource res : moduls) {
            for(BaseResource r : categorys) {
                if(r.getParentId().equals(res.getId()))
                    res.getSubResources().add(r);
            }
        }

        return moduls;
    }

}
